﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionToWhere
{
    internal class BaseExpressionVisitor : ExpressionVisitor
    {
        protected StringBuilder sb;
        protected bool searchNull;
        protected string dbType;

        public BaseExpressionVisitor()
        {
            sb = new StringBuilder();
        }

        public BaseExpressionVisitor(bool searchNull, string dbType = "SqlServer")
        {
            this.sb = new StringBuilder();
            this.searchNull = searchNull;
            this.dbType = dbType;
        }

        public virtual StringBuilder GetResult()
        {
            if (!ExpressionProcesser.Parametric)
            {
                foreach (KeyValuePair<string, object> item in ExpressionProcesser.Parameters)
                {
                    //('aaa','bbb','ccc')是在in/not in中使用的，两端不需要再加引号
                    if (item.Key.StartsWith($"@{Config.InConditionPrefix}") && item.Value is List<string> list)
                    {                        
                        for (int i = 0; i < list.Count; i++)
                        {
                            list[i] = "'" + list[i].Replace("'", "''") + "'";
                        }
                        sb = sb.Replace($"{item.Key}", $"({string.Join(",", list)})");
                    }
                    else if (item.Value != null)
                    {
                        sb = sb.Replace($"{item.Key}", $"'{item.Value.ToString().Replace("'", "''")}'");
                    }
                    else
                    {
                        throw new NotSupportedException($"item.Value Can't Be Null in GetResult()");
                    }
                }
                ExpressionProcesser.Parameters.Clear();
            }
            return sb;
        }

        protected bool IsLogicOperator(ExpressionType expressionType)
        {
            switch (expressionType)
            {
                case ExpressionType.AndAlso:
                case ExpressionType.OrElse:
                    return true;
                default:
                    return false;
            }
        }

        protected bool IsCompareOperator(ExpressionType expressionType)
        {
            switch (expressionType)
            {
                case ExpressionType.Equal:
                case ExpressionType.NotEqual:
                case ExpressionType.LessThan:
                case ExpressionType.LessThanOrEqual:
                case ExpressionType.GreaterThan:
                case ExpressionType.GreaterThanOrEqual:
                    return true;
                default:
                    return false;
            }
        }

        protected string GetOperator(ExpressionType type)
        {
            switch (type)
            {
                case ExpressionType.AndAlso: return "AND";
                case ExpressionType.OrElse: return "OR";
                case ExpressionType.Or: return "|";
                case ExpressionType.And: return "&";
                case ExpressionType.GreaterThan: return ">";
                case ExpressionType.GreaterThanOrEqual: return ">=";
                case ExpressionType.LessThan: return "<";
                case ExpressionType.LessThanOrEqual: return "<=";
                case ExpressionType.Equal: return "=";
                case ExpressionType.NotEqual: return "<>";
                case ExpressionType.Add: return "+";
                case ExpressionType.Subtract: return "-";
                case ExpressionType.Multiply: return "*";
                case ExpressionType.Divide: return "/";
                case ExpressionType.Modulo: return "%";
                default: throw new NotSupportedException($"Unknown ExpressionType {type}");
            }
        }
    }
}
